package com.yunxin.server.advice;

import com.yunxin.common.utils.JacksonUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * @author zero°
 * @description 请求响应日志打印
 * @since 2020/07/28
 */
@Aspect
@Component
@Slf4j
public class ControllerMethodLogAspect {

    private static final Set<String> WHITE_METHOD_LOG = new HashSet<>();

    static {
        WHITE_METHOD_LOG.add("index");
        WHITE_METHOD_LOG.add("getAreas");
        WHITE_METHOD_LOG.add("captcha");
    }
    @Around(//"execution(* com.yunxin.admin.system.api.core.*.*.*(..)) ||" +
            //" execution(* com.yunxin.admin.system.api.system.*.*(..)) ||" +
            " execution(* com.yunxin.gateway.api.*.*(..))")
    public Object aroundControllerMethodLog(ProceedingJoinPoint pdj) throws Throwable {
        Object result;
        MethodLogEntry entry = new MethodLogEntry();
        Signature signature = pdj.getSignature();
        String methodName;
        if (signature instanceof MethodSignature methodSignature) {
            Class<?> declaringType = methodSignature.getDeclaringType();
            methodName = methodSignature.getName();
            entry.setDeclaringType(declaringType.getCanonicalName());
            entry.setMethodName(methodName);
            entry.setArgs(pdj.getArgs());
        }
        boolean isLog = false;
        if (!WHITE_METHOD_LOG.contains(entry.getMethodName())) {
            isLog = true;
            log.info("aroundControllerMethodLog, 请求方法宿主类:{}, 请求方法名:{}, 参数为:{}",
                    entry.getDeclaringType(), entry.getMethodName(), entry.getArgs());
        }
        result = pdj.proceed();
        if (isLog) {
            log.info("aroundControllerMethodLog, 请求方法宿主类:{}, 请求方法名:{}, 返回结果为:{}",
                    entry.getDeclaringType(), entry.getMethodName(),
                    JacksonUtils.X.format(result));
        }
        return result;
    }

    @Data
    private static class MethodLogEntry {

        private String declaringType;
        private String methodName;
        private Object[] args;
    }
}
